package com.ctg.behavior.calc.impala.transfer.addictions;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.ctg.behavior.calc.common.CtSQLParam;
import com.ctg.behavior.calc.impala.report.addictions.CtAddictionsTimesReport;
import com.ctg.behavior.calc.impala.transfer.CtFilterTransfer;
import com.ctg.behavior.calc.utils.CtCalcPropertyUtils;
import com.ctg.behavior.calc.utils.CtCalcSQLUtils;
import com.ctg.behavior.common.calc.CtCalc;
import com.ctg.behavior.common.calc.CtCalcFilter;
import com.ctg.behavior.common.calc.CtCalcPropertyType;
import com.ctg.behavior.common.consts.CtAggregatorConsts;
import com.ctg.behavior.common.consts.CtCalcConsts;
import com.ctg.behavior.common.consts.CtFieldConsts;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CtAddictionsPeriodTransfer extends CtFilterTransfer {

	@Override
	public String doTransfer(CtCalc calcObject, CtSQLParam sqlParam) {

		if (!(calcObject instanceof CtAddictionsTimesReport)) {
			log.warn("calcObject is not CtAddictionsReport, class={}", calcObject.getClass());
			log.warn("calcObject: {}", JSON.toJSON(calcObject));
			return "";
		}
		CtAddictionsTimesReport report = (CtAddictionsTimesReport) calcObject;
		log.info("report={}", JSON.toJSONString(report));

		// 分组属性字段
		CtCalcPropertyType byProperty = CtCalcPropertyUtils.getValueType(report.getByField());
		// 统计维度事件及事件属性字段
		CtCalcPropertyType measureEvent = CtCalcPropertyUtils.getValueType(report.getMeasure().getEventId());

		StringBuilder impalaSQL = new StringBuilder();

		for (int bucketIndex = 0; bucketIndex < report.getBuckets().size(); bucketIndex++) {
			String bucketSQL = this.transferPeriodReport(report, bucketIndex, byProperty, measureEvent);
			if (bucketIndex > 0) {
				impalaSQL.append(" UNION ");
			}
			impalaSQL.append(bucketSQL);
		}

		log.info("reportSQL={}", impalaSQL);

		return impalaSQL.toString();

	}

	public String transferPeriodReport(CtAddictionsTimesReport report, Integer bucketIndex, CtCalcPropertyType byProperty, CtCalcPropertyType measureEvent) {

		StringBuilder impalaSQL = new StringBuilder();

		String userIdsSQL = this.transferUserIdsReport(report);
		if (StringUtils.isEmpty(userIdsSQL)) {
			return "";
		}

		impalaSQL.append(" SELECT ");
		impalaSQL.append(" \"").append(bucketIndex).append("\" AS bucketIndex ");

		if (StringUtils.isEmpty(byProperty.getProperty())) {
			// 用户行为日期
			if (CtCalcConsts.UNIT_TYPE_DAY.equals(report.getUnit())) {
				// 用户行为日期 - 按天查看
				impalaSQL.append(" , te.event_date AS eventDate ");
			} else {
				// 用户行为日期 - 按全部/周/月查看
				impalaSQL.append(" , \"").append(report.getTheCalcFromDate()).append("\" AS eventDate ");
			}
		} else {
			// 指定分组字段
			impalaSQL.append(" , ").append(byProperty.getProperty()).append(" AS ").append(byProperty.getProperty());
		}

		impalaSQL.append(" FROM ( ").append(userIdsSQL).append(" ) T0 ");

		impalaSQL.append(" WHERE 1=1 ");

		if (bucketIndex > 0) {
			impalaSQL.append(" AND T0.total >= '").append(report.getBuckets().get(bucketIndex)).append("' ");
		}
		if (bucketIndex < (report.getResultBucketParam().size() - 1)) {
			impalaSQL.append(" AND T0.total < '").append(report.getBuckets().get(bucketIndex)).append("' ");
		}

		// 分组(group by) - 区分
		{
			if (StringUtils.isEmpty(byProperty.getProperty()) && CtCalcConsts.UNIT_TYPE_DAY.equals(report.getUnit())) {
				/*** 用户行为日期 ***/
				impalaSQL.append(" GROUP BY te.event_date ");
			} else {
				/*** 指定分组字段 ***/
				impalaSQL.append(" GROUP BY ").append(byProperty.getProperty());
			}
		}
		// LIMIT - 防止分组属性字段导致查询的记录很多
		{
			impalaSQL.append(" LIMIT 1000 ");
		}

		return impalaSQL.toString();

	}

	public String transferUserIdsReport(CtAddictionsTimesReport report) {
		StringBuilder impalaSQL = new StringBuilder();

		// 分组属性字段
		CtCalcPropertyType byProperty = CtCalcPropertyUtils.getValueType(report.getByField());
		// 统计维度事件及事件属性字段
		CtCalcPropertyType measureEvent = CtCalcPropertyUtils.getValueType(report.getMeasure().getEventId());
		
		impalaSQL.append(" SELECT te.user_id AS userId ");

		if (StringUtils.isEmpty(byProperty.getProperty())) {
			// 用户行为日期
			if (CtCalcConsts.UNIT_TYPE_DAY.equals(report.getUnit())) {
				// 用户行为日期 - 按天查看
				impalaSQL.append(" , te.event_date AS eventDate ");
			} else {
				// 用户行为日期 - 按全部/周/月查看
				impalaSQL.append(" , \"").append(report.getTheCalcFromDate()).append("\" AS eventDate ");
			}
		} else {
			// 指定分组字段
			impalaSQL.append(" , ").append(byProperty.getProperty()).append(" AS ").append(byProperty.getProperty());
		}
		if (CtCalcConsts.MEASURE_TYPE_TIMES.equals(report.getMeasureType()) && StringUtils.isEmpty(measureEvent.getProperty())) {
			// 计算事件的总次数
			impalaSQL.append(" , count(*) AS total ");
		} else if (CtCalcConsts.MEASURE_TYPE_TIMES.equals(report.getMeasureType()) && !StringUtils.isEmpty(measureEvent.getProperty())) {
			// 用户指定: 统计维度事件及事件属性
			String aggregator = report.getMeasure().getAggregator();
			if (CtAggregatorConsts.KEY_SUM.equals(aggregator)) {
				// 总和
				impalaSQL.append(" , SUM(te.").append(measureEvent.getProperty()).append(") AS total");
			} else if (CtAggregatorConsts.KEY_AVG.equals(aggregator)) {
				// 均值
				impalaSQL.append(" , AVG(te.").append(measureEvent.getProperty()).append(") AS total");
			} else if (CtAggregatorConsts.KEY_MAX.equals(aggregator)) {
				// 均值
				impalaSQL.append(" , MAX(te.").append(measureEvent.getProperty()).append(") AS total");
			} else if (CtAggregatorConsts.KEY_MIN.equals(aggregator)) {
				// 均值
				impalaSQL.append(" , MIN(te.").append(measureEvent.getProperty()).append(") AS total");
			} else {
				// 去重数
				impalaSQL.append(" , count(*) AS total ");
			}
		} else {
			return "";
		}
		// 2. 表关联
		{
			impalaSQL.append(" FROM a_event_parquet_").append(report.getAppId()).append(" te ");
			// 若指定用户筛选条件，则需要关联调用户表
			if (!report.getUserFilter().getConditions().isEmpty()) {
				// 2.1 如果有用户属性筛选条件，则进行用户表关联( a_user_kudu_{appId})
				impalaSQL.append(" JOIN  a_user_kudu_").append(report.getAppId()).append(" tu ");
				impalaSQL.append(" ON te.user_id = tu.user_id ");
			}
			impalaSQL.append(" WHERE 1=1 ");
		}
		// 事件满足筛选条件
		{
			CtCalcFilter filter = report.getFilter();
			String conditionsSQL = super.doTransfer(filter, CtSQLParam.createAliasParam("te"));
			if (!CtCalcSQLUtils.isEmptyCondtions(conditionsSQL)) {
				impalaSQL.append(" AND ").append(conditionsSQL);
			}
		}
		// 用户符合筛选条件
		{
			CtCalcFilter filter = report.getUserFilter();
			String conditionsSQL = super.doTransfer(filter, CtSQLParam.createAliasParam("tu"));
			if (!CtCalcSQLUtils.isEmptyCondtions(conditionsSQL)) {
				impalaSQL.append(" AND ").append(conditionsSQL);
			}
		}
		// 用户进行 - 指定事件(若有明确事件标识) / 统计维度事件
		if (!StringUtils.isEmpty(report.getEventId()) && !CtFieldConsts.FIELD_ANYTHING.equals(report.getEventId())) {
			impalaSQL.append(" AND event = '").append(report.getEventId()).append("' ");
		}
		
		// 指定本次计算的时间范围
		impalaSQL.append(" AND te.event_date <= '").append(report.getTheCalcToDate()).append("' ");
		impalaSQL.append(" AND te.event_date >= '").append(report.getTheCalcFromDate()).append("' ");
		// 5. 分组(group by) - 区分
		{
			impalaSQL.append(" GROUP BY te.user_id ");
			if (StringUtils.isEmpty(byProperty.getProperty()) && CtCalcConsts.UNIT_TYPE_DAY.equals(report.getUnit())) {
				/*** 用户行为日期 ***/
				impalaSQL.append(" , te.event_date ");
			} else {
				/*** 指定分组字段 ***/
				impalaSQL.append(" , ").append(byProperty.getProperty());
			}
		}

		return impalaSQL.toString();
	}

}
